/**
 * Copyright 2011 Weldon Sams
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.siamnet.java.wwiki;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

/**
 * Wwiki - simple wiki engine
 * @author Weldon Sams
 */
public class Wwiki {
	
	private static String testString = "'''''Bold italic text'''''\n" +
		"'''Bold text'''\n" +
		"''Italic text''\n" +
		"[http://www.google.com]\n" +
		"[http://www.google.com | Google]\n" +
		"{http://example.com/image.png}\n" +
		"{http://example.com/image.png|http://images.google.com}\n" +
		"! h1\n" +
		"!! h2\n" +
		"!!! h3\n" +
		"!!!! h4\n" +
		"!!!!! h5\n" +
		"!!!!!! h6\n" +
		"----\n" +
		"* Bullet 1\n";

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Wwiki wwiki = new Wwiki();
		System.out.println(wwiki.run(testString));
	}

	/**
	 * Run wwiki
	 */
	private String run(String input) {
		int cnt = 0;
		String[] wikiContent = input.split("\n");
		String renderedContent = "";
		LinkedHashMap<Integer, String> wikiContentHashMap = new LinkedHashMap<Integer, String>();
		TreeMap wikiContentTreeMap = new TreeMap();
		for ( String line : wikiContent ) {
			wikiContentHashMap.put(cnt, line);
			wikiContentTreeMap.put(cnt, line);
			cnt++;
		}
		//Set set = wikiContentHashMap.entrySet();
		Set set = wikiContentTreeMap.entrySet();
        Iterator iterator = set.iterator();
        while ( iterator.hasNext() ) {		
        	Map.Entry<Integer, String> mapEntry = (Map.Entry<Integer, String>) iterator.next();
            Integer key = (Integer) mapEntry.getKey();
            String value = (String) mapEntry.getValue();
			renderedContent += renderAll(wikiContentHashMap.get(key)) + "<br />\n";
        }
		
		return renderedContent;
	}
	
	/**
	 * Run all rendering methods on line.
	 * @param input
	 * @return String Rendered wiki syntax
	 */
	public String renderAll(String input) {
		if ( input == null ) {
			return input;
		}
		input = renderEmphasis(input);
		input = renderLinks(input);
		input = renderImages(input);
		input = renderSections(input);
		input = renderOther(input);
		input = renderLists(input);
		
		return input;
	}
	
	/**
	 * Run emphasis renderer
	 * @param input
	 * @return String Rendered wiki syntax
	 */
	public String renderEmphasis(String input) {
		if ( input == null ) {
			return input;
		}
		Pattern pattern;
		Matcher matcher;
		String regex;
		
		// Bold and Italic
		// '''''word''''' => <strong><em>word</em></strong>
		regex = "'''''(.+?)'''''";
		pattern = Pattern.compile(regex);
		matcher = pattern.matcher(input);
		if ( matcher.find() ) {
			input = input.replaceAll(regex, "<strong><em>$1</em></strong>");
		}
		
		// Bold
		// '''word''' => <strong>word</strong>
		regex = "'''(.+?)'''";
		pattern = Pattern.compile(regex);
		matcher = pattern.matcher(input);
		if ( matcher.find() ) {
			input = input.replaceAll(regex, "<strong>$1</strong>");
		}
		
		// Italic
		// ''word'' => <em>word</em>
		regex = "''(.+?)''";
		pattern = Pattern.compile(regex);
		matcher = pattern.matcher(input);
		if ( matcher.find() ) {
			input = input.replaceAll(regex, "<em>$1</em>");
		}
		
		return input;
	}
	
	/**
	 * Run links renderer
	 * @param input
	 * @return String Rendered wiki syntax
	 */
	public String renderLinks(String input) {
		if ( input == null ) {
			return input;
		}
		Pattern pattern;
		Matcher matcher;
		String regex;
		
		// Link with link text
		// [http://www.example.com | Example.com] => <a href="http://www.example.com">Example.com</a>
		regex = "\\[\\s*(http.+?)\\s*\\|\\s*(.+?)\\s*\\]";
		pattern = Pattern.compile(regex);
		matcher = pattern.matcher(input);
		if ( matcher.find() ) {
			input = input.replaceAll(regex, "<a href=\"$1\">$2</a>");
		}
		
		// Link with link text being the url
		// [http://www.example.com] => <a href="http://www.example.com">http://www.example.com</a>
		regex = "\\[\\s*(http.+?)\\s*\\]";
		pattern = Pattern.compile(regex);
		matcher = pattern.matcher(input);
		if ( matcher.find() ) {
			input = input.replaceAll(regex, "<a href=\"$1\">$1</a>");
		}
		
		return input;
	}
	
	/**
	 * Run images renderer
	 * @param input
	 * @return String Rendered wiki syntax
	 */
	public String renderImages(String input) {
		if ( input == null ) {
			return input;
		}
		Pattern pattern;
		Matcher matcher;
		String regex;
		
		// Image as link (Must go before 'Image' the basic embedding an image.)
		// {http://www.example.com/image.png|http://www.example.com/goHere.html} => <a href="http://www.example.com/goHere.html"><img src="http://www.example.com" alt="http://www.example.com" /></a>
		regex = "\\{\\s*(http.+?)\\s*\\|\\s*(http.+?)\\s*\\}";
		pattern = Pattern.compile(regex);
		matcher = pattern.matcher(input);
		if ( matcher.find() ) {
			input = input.replaceAll(regex, "<a href=\"$2\"><img src=\"$1\" alt=\"$1\" /></a>");
		}
		
		// Image
		// {http://www.example.com/image.png} => <img src="http://www.example.com" alt="http://www.example.com" />
		regex = "\\{(http.+?)\\}";
		pattern = Pattern.compile(regex);
		matcher = pattern.matcher(input);
		if ( matcher.find() ) {
			input = input.replaceAll(regex, "<img src=\"$1\" alt=\"$1\" />");
		}
		
		return input;
	}
	
	/**
	 * Run sections renderer
	 * @param input
	 * @return String Rendered wiki syntax
	 */
	public String renderSections(String input) {
		if ( input == null ) {
			return input;
		}
		Pattern pattern;
		Matcher matcher;
		String regex;
		
		// h6 
		// !!!!!! h6 heading => <h6>h6 heading</h6>
		regex = "^\\s*!!!!!!\\s*(.+)$";
		pattern = Pattern.compile(regex);
		matcher = pattern.matcher(input);
		if ( matcher.find() ) {
			input = input.replaceAll(regex, "<h6>$1</h6>");
		}
		
		// h5 
		// !!!!! h5 heading => <h5>h5 heading</h5>
		regex = "^\\s*!!!!!\\s*(.+)$";
		pattern = Pattern.compile(regex);
		matcher = pattern.matcher(input);
		if ( matcher.find() ) {
			input = input.replaceAll(regex, "<h5>$1</h5>");
		}
		
		// h4 
		// !!!! h4 heading => <h4>h4 heading</h4>
		regex = "^\\s*!!!!\\s*(.+)$";
		pattern = Pattern.compile(regex);
		matcher = pattern.matcher(input);
		if ( matcher.find() ) {
			input = input.replaceAll(regex, "<h4>$1</h4>");
		}
		
		// h3 
		// !!! h3 heading => <h3>h3 heading</h3>
		regex = "^\\s*!!!\\s*(.+)$";
		pattern = Pattern.compile(regex);
		matcher = pattern.matcher(input);
		if ( matcher.find() ) {
			input = input.replaceAll(regex, "<h3>$1</h3>");
		}
		
		// h2 
		// !! h2 heading => <h2>h2 heading</h2>
		regex = "^\\s*!!\\s*(.+)$";
		pattern = Pattern.compile(regex);
		matcher = pattern.matcher(input);
		if ( matcher.find() ) {
			input = input.replaceAll(regex, "<h2>$1</h2>");
		}
		
		// h1 
		// ! h1 heading => <h1>h1 heading</h1>
		regex = "^\\s*!\\s*(.+)$";
		pattern = Pattern.compile(regex);
		matcher = pattern.matcher(input);
		if ( matcher.find() ) {
			input = input.replaceAll(regex, "<h1>$1</h1>");
		}
		
		return input;
	}
	
	/**
	 * Render various uncategorized html elements.
	 * @param input
	 * @return String Rendered wiki syntax
	 */
	public String renderOther(String input) {
		if ( input == null ) {
			return input;
		}
		Pattern pattern;
		Matcher matcher;
		String regex;
		
		// Horizontal rule
		// ---- => <hr />
		regex = "----";
		pattern = Pattern.compile(regex);
		matcher = pattern.matcher(input);
		if ( matcher.find() ) {
			input = input.replaceAll(regex, "<hr />");
		}
		
		return input;
	}
	
	public String renderLists(String input) {
		if ( input == null ) {
			return input;
		}
		Pattern pattern;
		Matcher matcher;
		String regex;
		
		// Horizontal rule
		// ---- => <hr />
		regex = "^\\*\\s*(.+?)$";
		pattern = Pattern.compile(regex);
		matcher = pattern.matcher(input);
		if ( matcher.find() ) {
			input = input.replaceAll(regex, "<ul><li>$1</li></ul>");
		}
		
		return input;
	}

}
